using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Controls;
using System.Windows.Media;
using System.Drawing;
using System.Windows.Media.Imaging;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;
using System.Runtime.InteropServices;
using System.Data;
using SkiaSharp;

namespace FaceCat
{
    /// <summary>
    /// 渲染视图
    /// </summary>
    public class FCUIView : FrameworkElement  //System.Windows.Controls.Control
    {
        /// <summary>
        /// 渲染视图
        /// </summary>
        /// <param name="native">方法库</param>
        public FCUIView()
        {
        }

        /// <summary>
        /// 设备库
        /// </summary>
        public WPFHost m_host;

        /// <summary>
        /// 方法库
        /// </summary>
        public FCNative m_native;

        /// <summary>
        /// 缓存的WPF位图对象
        /// </summary>
        public RenderTargetBitmap m_rtb;

        /// <summary>
        /// 缓存的WPF图像
        /// </summary>
        public WriteableBitmap m_wBitmap;

        /// <summary>
        /// 绘图对象
        /// </summary>
        public WPFPaint m_wpfPaint;

        /// <summary>
        /// 加载方法
        /// </summary>
        public void onLoad()
        {
            m_native = new FCNative();
            m_wpfPaint = new WPFPaint();
            m_native.setPaint(m_wpfPaint);
            m_host = new WPFHost();
            m_host.m_uiView = this;
            m_host.setNative(m_native);
            m_native.setHost(m_host);
            m_native.update();
        }

        /// <summary>
        /// 重绘方法
        /// </summary>
        /// <param name="drawingContext">参数</param>
        protected override void OnRender(DrawingContext drawingContext)
        {
            int width = (int)ActualWidth, height = (int)ActualHeight;
            if (width > 0 && height > 0)
            {
                if (m_wBitmap != null)
                {
                    drawingContext.DrawImage(m_wBitmap, new System.Windows.Rect(0, 0, width, height));
                }
            }
        }

        /// <summary>
        /// 大小改变方法
        /// </summary>
        /// <param name="sizeInfo">参数</param>
        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            base.OnRenderSizeChanged(sizeInfo);
            System.Windows.Size newSize = sizeInfo.NewSize;
            m_native.setSize(new FCSize((int)newSize.Width, (int)newSize.Height));
            m_native.update();
            invalidate(new FCRect(0, 0, m_native.getSize().cx, m_native.getSize().cy));
        }

        /// <summary>
        /// 刷新方法
        /// </summary>
        public void invalidate(FCRect clipRect)
        {
            int width = (int)ActualWidth, height = (int)ActualHeight;
            if (width > 0 && height > 0)
            {
                if (m_wBitmap == null || m_wBitmap.Width != width || m_wBitmap.Height != height)
                {
                    m_wBitmap = new WriteableBitmap(width, height, 96, 96, PixelFormats.Bgr32, null);
                }
                m_wBitmap.Lock();
                IntPtr buffer = m_wBitmap.BackBuffer;
                int pW = m_wBitmap.PixelWidth;
                int pH = m_wBitmap.PixelHeight;
                int stride = m_wBitmap.BackBufferStride;
                if (clipRect.left < 0)
                {
                    clipRect.left = 0;
                }
                if (clipRect.top < 0)
                {
                    clipRect.top = 0;
                }
                if (clipRect.right > m_native.getSize().cx)
                {
                    clipRect.right = m_native.getSize().cx;
                }
                if (clipRect.bottom > m_native.getSize().cy)
                {
                    clipRect.bottom = m_native.getSize().cy;
                }
                if (clipRect.bottom < 0)
                {
                    clipRect.bottom = 0;
                }
                if (clipRect.right < 0)
                {
                    clipRect.right = 0;
                }
                SKImageInfo imageInfo = new SKImageInfo(pW, pH, SKColorType.Bgra8888);
                using (SKBitmap bitmap = new SKBitmap(imageInfo))
                {
                    bitmap.InstallPixels(imageInfo, buffer, stride);
                    using (SKCanvas canvas = new SKCanvas(bitmap))
                    {
                        m_wpfPaint.m_canvas = canvas;
                        m_wpfPaint.beginPaint(IntPtr.Zero, new FCRect(0, 0, pW, pH), clipRect);
                        m_native.onPaint(clipRect);
                        m_wpfPaint.endPaint();
                    }
                    SKPixmap pixmap = bitmap.PeekPixels();
                    pixmap.ReadPixels(imageInfo, buffer, stride, 0, 0);
                }
                m_wBitmap.AddDirtyRect(new Int32Rect(clipRect.left, clipRect.top, clipRect.right - clipRect.left, clipRect.bottom - clipRect.top));
                m_wBitmap.Unlock();
            }
            this.InvalidateVisual();
        }
    }
}
